﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TCC_Hotel.Entidades;
using TCC_Hotel.Repositorio;
using System.Web.Caching;

namespace TCC_Hotel.Serviços.BDServices
{
    public class ApartamentoService
    {
        ApartamentoRepositorio repositorio = new ApartamentoRepositorio();

        /// <summary>
        /// Insere um apartamento no banco de dados
        /// </summary>
        /// <param name="empresa">apartamento que vai ser inserido</param>
        /// <returns>retorna true se inseriu ou false se não</returns>
        public bool CadastrarApartamento(Apartamento apartamento)
        {
            return repositorio.CadastrarApartamento(apartamento);
        }

        /// <summary>
        /// Verifica se o apartamento tem reserva
        /// </summary>
        /// <param name="empresa">apartamento que vai ser verificado</param>
        /// <returns>retorna true se tem reserva mas indisponível</returns>
        public bool VerificarReservaApartamento(int Numeroapartamento)
        {
            //recupera todos os apartamentos ocupados nesse momento
            ReservaService reserva_Service = new ReservaService();
            List<int> listaApartamentosOcupadosFaturados = reserva_Service.ListarReservasFaturadasCache().Select(i => i.Numero_Apartamento).ToList();
            List<int> listaApartamentosOcupadosParticulares = reserva_Service.ListarReservasParticularesCache().Select(i => i.Numero_Apartamento).ToList();

            //verifica se o apartamento corrente esta dentro dos ocupados
            if (listaApartamentosOcupadosFaturados.Contains(Numeroapartamento) || listaApartamentosOcupadosParticulares.Contains(Numeroapartamento))
            {
                return true;
            }
            //se não, é preciso liberá-lo para outros hóspedes
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Verifica se o apartamento esta indisponivel e livre. Se sim a camareira deve limpá-lo
        /// e liberá-lo
        /// </summary>
        /// <param name="empresa">apartamento que vai ser verificado</param>
        /// <returns>retorna true se esta livre mas indisponível</returns>
        public bool VerificarOcupacaoApartamento(int Numeroapartamento)
        {
            //recupera todos os apartamentos ocupados nesse momento
            FluxoHospedesService fluxo_Service = new FluxoHospedesService();
            List<int> listaApartamentosOcupados = fluxo_Service.ListarFluxoHospedesAgoraCache().Select(i => i.Numero_Apartamento).ToList();
                        
            //verifica se o apartamento corrente esta dentro dos ocupados
            if (listaApartamentosOcupados.Contains(Numeroapartamento))
            {
                return true;
            }
            //se não, é preciso liberá-lo para outros hóspedes
            else
            {
                return false;
            }           
        }

        /// <summary>
        /// Retorna os apartamentos do banco de dados
        /// </summary>
        /// <returns>Lista com os apartamentos</returns>
        public List<Apartamento> RecuperarApartamentos()
        {
            return repositorio.RecuperarApartamentos();
        }

        /// <summary>
        /// Retorna os apartamentos ocupados no momento do banco de dados
        /// </summary>
        /// <returns>Lista com os apartamentos</returns>
        public List<int> RecuperarApartamentosOcupados()
        {
            FluxoHospedesService fluxo_Service = new FluxoHospedesService();
            List<int> listaNumeroApartamentosOcupados = fluxo_Service.ListarFluxoHospedesAgoraCache().OrderBy(i=>i.Numero_Apartamento).Select(i => i.Numero_Apartamento).ToList();
            return listaNumeroApartamentosOcupados;
        }

        /// <summary>
        /// Exclui um apartamento do banco de dados
        /// </summary>
        /// <param name="empresa">numero do apartamento que vai ser excluido</param>
        /// <returns>retorna true se excluiu ou false se não</returns>
        public bool ExcluirApartamento(int numero)
        {
            return repositorio.ExcluirApartamento(numero);
        }

        /// <summary>
        /// Edita um apartamento no banco de dados
        /// </summary>
        /// <param name="apartamento">novo apartamento</param>
        /// <param name="numero">numero do apartamento que vai ser editado</param>
        /// <returns>retorna true se editou ou false se não</returns>
        public bool EditarApartamento(int numero, Apartamento apartamento)
        {
            return repositorio.EditarApartamento(numero, apartamento);
        }

        /// <summary>
        /// Edita a disponibilidade de um apartamento no banco de dados
        /// </summary>
        /// <param name="apartamento">novo status</param>
        /// <param name="numero">numero do apartamento que vai ser editado</param>
        /// <returns>retorna true se editou ou false se não</returns>
        public bool EditarDisponibilidadeApartamento(int numero, bool status)
        {
            return repositorio.EditarDisponibilidadeApartamento(numero, status);
        }

        /// <summary>
        /// Retorna o Apartamento especifico do banco de dados
        /// </summary>
        /// <returns>Apartamento recuperada</returns>
        public Apartamento RecuperarDetalhesApartamento(int numero)
        {
            return repositorio.RecuperarDetalhesApartamento(numero);
        }
        
        /// <summary>
        /// Verifica disponibilidade do apartamento
        /// </summary>
        /// <param name="numero">Numero do apartamento</param>
        /// <returns>Se está disponivel ou não</returns>
        public bool VerificaDisponibilidade(int numero)
        {
            Apartamento apartamento = RecuperarDetalhesApartamento(numero);

            if (apartamento.Disponibilidade)
                return true;
            else
                return false;
            
        }

        /// <summary>
        /// Verifica se a informação ja esta gravada em cache, se tiver recupera, 
        /// senao faz a consulta e grava em cache
        /// </summary>
        /// <returns>Lista de apartamentos</returns>
        public List<Apartamento> ListarApartamentosCache()
        {
            List<Apartamento> apartamentos = new List<Apartamento>();

            //Verifica se a informação esta guardada em cache
            if (HttpContext.Current.Cache.Get("Lista_Apartamentos") == null)
            {
                //Consulta as apartamentos no banco
                apartamentos = RecuperarApartamentos();

                //Armazena a lista de apartamentos em cache de 1 minuto para evitar muitas consultas ao banco
                HttpContext.Current.Cache.Add("Lista_Apartamentos", apartamentos, null,
                                 DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.High, null);

            }

           //caso essa informaçao ja estiver no cache
            else
            {
                //Resgata informação do cache
                apartamentos = (List<Apartamento>)HttpContext.Current.Cache.Get("Lista_Apartamentos");

            }

            return apartamentos;
        }

        
    }
}